package com.dbs.zstp.common.service.impl;

import com.dbs.zstp.common.model.Example;
import com.dbs.zstp.common.model.Page;
import com.dbs.zstp.common.service.BaseService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Column;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 
 * 包名：com.dbs.common.service.impl
 * 功能：TODO 通用service实现类
 * 作者：hualn
 * 日期：2018年1月18日 上午10:11:08
 */
public abstract class BaseServiceImpl<T> implements BaseService<T> {

    /**
     * 完整新增
     * 注:未付值变量将插入NULL到字段中
     *
     * @param model 实体参数
     * @return 操作后的实体
     * @throws Exception
     */
    @Transactional
    public T insert(T model) throws Exception {
        getMapper().insert(model);
        return model;
    }

    /**
     * 选择新增
     * 注:未付值变量将被过滤掉
     *
     * @param model 实体参数
     * @return 操作后的实体
     * @throws Exception
     */
    @Transactional
    public T insertSelective(T model) throws Exception {
        getMapper().insertSelective(model);
        return model;
    }

    /**
     * 批量新增
     * 注:内部采用选择性新增
     *
     * @param modelList 实体参数集合
     * @return 操作的实体集合
     * @throws Exception
     */
    @Transactional
    public List<T> insertList(List<T> modelList) throws Exception {
        for (T recode : modelList) {
            getMapper().insertSelective(recode);
        }
        return modelList;
    }


    /**
     * 根据主键删除
     * 注:主键必须只有一个,参数类型须跟实体成员变量类型相同
     *
     * @param key 主键值
     * @return 改变条数
     * @throws Exception
     */
    @Transactional
    public int deleteByPrimaryKey(Object key) throws Exception {
        return getMapper().deleteByPrimaryKey(key);
    }


    /**
     * 实体精确条件删除
     * 注:根据实体中非空成员变量为条件进行单条记录(或批量)删除
     *
     * @param model 实体参数
     * @return 改变条数
     * @throws Exception
     */
    @Transactional
    public int delete(T model) throws Exception {
        return getMapper().delete(model);
    }

    /**
     * 批量实体精确删除
     * 注:* 注:循环根据实体中非空成员变量为条件进行单条记录(或批量)删除
     *
     * @param modelList 实体参数集合
     * @return 改变条数
     * @throws Exception
     */
    @Transactional
    public int delete(List<T> modelList) throws Exception {
        int i = 0;
        if (null != modelList) {
            for (T model : modelList) {
                i += this.delete(model);
            }
        }
        return i;
    }

    /**
     * 根据主键完整修改
     * 注:未付值成员变量对应字段会被改为NULL
     * 注:主键是实体里面的带有ID注解的成员变量
     * 注:主键值不能为空
     *
     * @param model 实体参数
     * @return 改变条数
     * @throws Exception
     */
    @Transactional
    public int updateByPrimaryKey(T model) throws Exception {
        return getMapper().updateByPrimaryKey(model);
    }


    /**
     * 根据主键选择修改
     * 注:未付值成员变量对应字段不会被修改
     * 注:主键是以实体里面的带有ID注解的成员变量,主键值不能为空
     *
     * @param model 实体参数
     * @return 改变条数
     * @throws Exception
     */
    @Transactional
    public int updateByPrimaryKeySelective(T model) throws Exception {
        return getMapper().updateByPrimaryKeySelective(model);
    }


    /**
     * 查询所有
     *
     * @return 结果集
     * @throws Exception
     */
    public List<T> selectAll() throws Exception {
        return getMapper().selectAll();
    }

    /**
     * 根据主键查询实体
     * 注:主键必须只有一个,参数类型须跟实体成员变量类型相同
     *
     * @param key 主键值
     * @return 实体结果
     * @throws Exception
     */
    public T selectByPrimaryKey(Object key) throws Exception {
        return getMapper().selectByPrimaryKey(key);
    }


    /**
     * 根据实体精确查询条数
     *
     * @param model 实体参数
     * @return 实体结果
     * @throws Exception
     */
    public int selectCount(T model) throws Exception {
        return getMapper().selectCount(model);
    }

    /**
     * 根据实体精确查询实体结果集
     *
     * @param model 实体参数
     * @return 实体结果集
     * @throws Exception
     */
    public List<T> select(T model) throws Exception {
        return getMapper().select(model);
    }

    /**
     * 根据实体精确查询单个实体
     *
     * @param model 实体参数
     * @return 实体结果
     * @throws Exception
     */
    public T selectOne(T model) throws Exception {
        return getMapper().selectOne(model);
    }

    /**
     * 根据实体参数和分页参数结果集
     *
     * @param model 实体参数
     * @param page  分页参数
     * @return 实体结果集
     * @throws Exception
     */
    public List<T> selectList(T model, Page page) throws Exception {
        Object example = getExample(model);

        if (null != page) {
            if (StringUtils.isNotBlank(page.getOrder())) {
                if (null == example) {
                    example = new Example(model.getClass());
                }

                String[] orderArr = page.getOrder().split(",");
                List<String> orderByList = new ArrayList<String>(orderArr.length);
                for (String order : orderArr) {
                    String[] orderParam = order.split(" ");
                    String orderColumn = orderParam[0];
                    String orderDir = "asc";
                    if (orderParam.length > 1) {
                        orderDir = orderParam[1];
                    }
                    Field field = model.getClass().getDeclaredField(StringUtils.trim(orderColumn));
                    if (null != field)
                        orderByList.add(field.getAnnotation(Column.class).name() + " " + orderDir);
                }

                if (example instanceof Example) {
                    ((Example) example).setOrderByClause(StringUtils.join(orderByList, ","));
                } else {
                    Method m = example.getClass().getMethod("setOrderByClause", String.class);
                    m.invoke(example, StringUtils.join(orderByList, ","));
                }
            }
            if (StringUtils.isNotBlank(page.getColumns())) {
                if (null == example) {
                    example = new Example(model.getClass());
                }
                if (example instanceof Example) {
                    ((Example) example).selectProperties(page.getColumns().split(","));
                }
            }

            if (page.isDistinct()) {
                if (null == example) {
                    example = new Example(model.getClass());
                }
                if (example instanceof Example) {
                    ((Example) example).setDistinct(page.isDistinct());
                } else {
                    Method m = example.getClass().getMethod("setDistinct", Boolean.class);
                    m.invoke(example, page.isDistinct());
                }
            }
            if (null != page && null != page.getLength()) {
                if (null == page.getStart()) {
                    page.setStart(0);
                }
//                PageHelper.startPage(page.getStart() / page.getLength() + 1, page.getLength());
            }
        }

        return getMapper().select(model);
    }

    public Object getExample(T t) {
        return null;
    }
}
